package com.pie4cloud.pie.job.api.utils;

import com.pie4cloud.pie.job.api.commons.Constant;
import com.pie4cloud.pie.job.api.entity.GatherMessageEntity;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;

public class FtpUtils {

	private static Logger logger = LoggerFactory.getLogger(FtpUtils.class);

	public static List<String> getAllBaseDirectory(FTPClient ftpClient, String baseAddress) {

		List<String> allBaseDirectory = new ArrayList<>();
		if (StringUtils.isBlank(baseAddress)) {
			return allBaseDirectory;
		} else {
			if (StringUtils.contains(baseAddress, Constant.GATHER_DIRECTORY_WILDCARD)) {
				String[] directorySlices = StringUtils.split(baseAddress, "\\*");
				List<String> tempDirectory = new ArrayList<>();
				for (String directorySlice: directorySlices) {
					if (tempDirectory.isEmpty()) {
						tempDirectory = getTempBaseDirectory(ftpClient,directorySlice);
					}else {
						List<String> sliceDirectory = new ArrayList<>();
						for (int i = 0; i < tempDirectory.size(); i++) {
							sliceDirectory.addAll(getTempBaseDirectory(ftpClient,tempDirectory.get(i)+"/"+directorySlice));
						}
						tempDirectory = sliceDirectory;
					}
				}
				allBaseDirectory = tempDirectory;
			}
			return allBaseDirectory;
		}
	}

	private static List<String> getTempBaseDirectory(FTPClient ftpClient,String baseAddress) {
		List<String> baseDirectory = new ArrayList<>();
		try {
			boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(baseAddress);
			if (changeWorkingDirectory) {
				return Arrays.asList(ftpClient.listNames());
			}else {
				return baseDirectory;
			}
		} catch (IOException e) {
			logger.error("change work dirctory {} fail",baseAddress,e);
			return baseDirectory;
		}
	}
	
	public static  boolean connect(FTPClient ftpClient,String hostname,int port, String username, String password) {
        try {
        	if (port != 0) {
				ftpClient.setDefaultPort(port);
			}
            ftpClient.connect(hostname);
            ftpClient.enterLocalPassiveMode();
            ftpClient.setBufferSize(1024);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding("UTF-8");
            if (ftpClient.login(username, password)) {
            	logger.info("connect ftp sussess!");
               return true;
            } else {
            	logger.error("connect ftp fail，username or passage error!");
                try {
                    disconnect(ftpClient);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
        	logger.error("connect ftp fail . message is : {} .",e.getMessage(),e);
        }
        return false;
    }
	
    public static void disconnect(FTPClient ftpClient) {
        if (ftpClient.isConnected()) {
            try {
                ftpClient.disconnect();
                logger.error("close ftp client sussess!");
            } catch (IOException e) {
            	logger.error("close ftp connect fail. fail message is : {}",e.getMessage(),e);
            }
        }
    }

	/**
	 *
	 * @param hostname 主机名
	 * @param  port 端口
	 * @param username 用户名
	 * @param password 密码
	 * @param workPath 远程地址
	 * @param localFileName 本地文件
	 * @param saveName 存储文件名
	 * @return
	 */
    public static  boolean upload(String hostname,int port, String username, String password, String workPath,String localFileName, String saveName) {
    	
    	FTPClient ftpClient = new FTPClient();
		InputStream inputStream = null;
        //1 测试连接
        if (connect(ftpClient,hostname,port, username, password)) {
            try {
            	boolean exits = ftpClient.changeWorkingDirectory(workPath);
            	if(!exits) {
            		ftpClient.makeDirectory(workPath);
            	}
				inputStream = new FileInputStream(new File(localFileName));
            	if (ftpClient.storeFile(saveName, inputStream)) {
            		disconnect(ftpClient);
            	}
            	return true;
            } catch (IOException e) {
                logger.error("upload file to ftp fail .",e);
            }finally {
				if(inputStream != null) {
					try {
						inputStream.close();
					} catch (IOException e) {
						logger.error("inputStream close fail.",e);
					}
				}
				if (ftpClient != null) {
					disconnect(ftpClient);
				}
			}
        }
        return false;
    }

	/**
	 *
	 * @param hostname 主机名
	 * @param username 用户名
	 * @param password 用户密码
	 * @param remoteFilePath 远程文件
	 * @param localPath 本地地址
	 * @param fileName 文件名
	 */
	public static void download(FTPClient ftpClient,String remoteFilePath,String localPath,String fileName) {

		File localDir = new File(localPath);
		if(!localDir.exists() || !localDir.isDirectory()) {
			localDir.mkdirs();
		}
		OutputStream ous=null;
		try {
			ous=new FileOutputStream(localPath + (StringUtils.endsWith(localPath,"/")?"":"/") + fileName);
			ftpClient.retrieveFile(remoteFilePath, ous);
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
			logger.error("download file fail.",e);
			e.printStackTrace();
		}finally {
			if(ous != null) {
				try {
					ous.close();
				} catch (IOException e) {
					logger.error("OutputStream close fail.",e);
				}
			}
		}
	}

	public static void scanAllFile(FTPClient ftpClient, List<String> allPath, String pathReg, Set<GatherMessageEntity> allFile) throws IOException {

		if (allFile == null) {
			allFile = new HashSet<>();
		}
		if(allPath == null) {
			return;
		}
		for (int i = 0; i < allPath.size(); i++) {
			String path = allPath.get(i);
			boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(path);
			if (!changeWorkingDirectory) {
				continue;
			}
			FTPFile[] ftpFiles = ftpClient.listFiles();
			for (FTPFile ftpFile: ftpFiles) {
				String workingDirectory = ftpClient.printWorkingDirectory();
				String filePath = StringUtils.join(new String[]{workingDirectory,ftpFile.getName()},"/");
				if (ftpFile.isDirectory()) {
					scanAllFile(ftpClient,Arrays.asList(filePath),pathReg,allFile);
					ftpClient.changeWorkingDirectory(workingDirectory);
				}
				if (ftpFile.isFile()) {
					try {
						GatherMessageEntity gatherMessageEntity = new GatherMessageEntity();
						String[] match = RegUtils.match(pathReg, filePath);
						gatherMessageEntity.setRemoteFilePath(filePath);
						gatherMessageEntity.setRegList(Arrays.asList(match));
						allFile.add(gatherMessageEntity);
					} catch (RegException e) {
						logger.warn("file {} is not match {}",filePath,pathReg);
					}
				}
			}
		}
	}

	public static void main(String[] args) throws IOException {

		FTPClient ftpClient = new FTPClient();
		boolean connect = connect(ftpClient, "10.110.172.157", 21, "hunanftp", "12345678");
		Set<GatherMessageEntity> allFile = new HashSet<>();
		scanAllFile(ftpClient,Arrays.asList("/CMADAAS/DATA/SURF/MERGE/CMPA/FAST/3HOR/2021/"),"/CMADAAS/DATA/SURF/MERGE/CMPA/FAST/3HOR/2021/20210723/Z_SURF_C_BABJ_20210723000441_P_CMPA_FAST_CHN_0P05_3HOR-PRE-2021072300.GRB2",allFile);
		Iterator<GatherMessageEntity> iterator = allFile.iterator();
		while (iterator.hasNext()) {
			GatherMessageEntity gatherMessageEntity = iterator.next();
			System.out.println(gatherMessageEntity);
		}
		disconnect(ftpClient);
	}
}
